home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / strx221.zip / STR.DOC < prev    next >
Text File  |  1993-05-18  |  63KB  |  1,657 lines

  1. Copyright (c) 1993 by Roy S. Woll 
  2.  
  3. Class "str", Version 2.2     5.16/93
  4.  
  5. You may distribute and sell any executable which results from using this code
  6. in your applications.  You may redistribute this source freely as long as you
  7. leave all files in their original form, including the copyright notice as is.
  8. You may NOT include any SOURCE code of this software with any program that is
  9. sold. 
  10.  
  11. I would sincerely welcome any comments/criticism/ideas you might have about
  12. the str or the regular expression class.
  13.  
  14.  
  15. Registration:
  16. -------------
  17. If you decide to use this product, you must register by one of the 
  18. following two methods.
  19.  
  20.    Online-registration:
  21.    --------------------
  22.  
  23.    You can also register strX directly on Compuserve by going to 
  24.    the SHAREWARE REGISTRATION section and looking for the product 
  25.    strX (Registration ID 925)
  26.  
  27.  
  28.    Mail
  29.    ----
  30.  
  31.    Register by sending $15.00 to 
  32.    Roy S. Woll, 1032 Summerplace Dr., San Jose, CA 95122.  
  33.  
  34.  
  35. By registering you will receive an enhanced version of the class that
  36. includes context sensitive regular expressions, and more extensive 
  37. documentation.
  38.  
  39. In addition those of you who register will receive a more powerful
  40. version of the regular expression class that includes context-sensitive
  41. regular expressions.  For instance you will easily be able to search or 
  42. replace a specific portion (flagged by '@') of a regular expression.
  43.  
  44.             
  45.            regX employeeX("Pay to the order of @[A-Za-z\\s]+$");
  46.            str paycheck("Payroll\nPay to the order of Roy S. Woll\n$50,000");
  47.            str employee;
  48.  
  49.            paycheck.search(employeeX,  &employee); 
  50.            paycheck.replace(employeeX,  "a lucky person");
  51.  
  52.        //
  53.        // After executing the above code, employee will contain the
  54.        // name of the person following the text "Pay to the order of ".
  55.        //
  56.        // employee = "Roy S. Woll"
  57.        // paycheck = "Payroll\nPay to the order of lucky person\n$50,000"
  58.        //   
  59.  
  60.  
  61.  
  62.  
  63. Support:
  64. --------
  65.  
  66.            ------------------------------------------
  67.            |                                        |
  68.            | Roy S. Woll                            |
  69.            | 1032 Summerplace Dr.                   |
  70.            | San Jose, CA 95122                     |
  71.            |                                        |
  72.            | CompuServe : 76207,2541                |
  73.            |                                        |
  74.            | Phone: (408) 778-2000 x4518  (day)     |
  75.            |        (408) 293-5893        (evening) |
  76.            |                                        |
  77.            ------------------------------------------
  78.  
  79.  
  80. ------------------------------------------------------------------------------
  81.  
  82.  
  83.           FILES:  THE FOLLOWING FILES ARE INCLUDED.
  84.           -----------------------------------------
  85.           str.doc        Documentation file for str class
  86.  
  87.           str.h          Interface file for str class
  88.           regX.h         Interface file for regular expression class
  89.           regXimp.h      Interface file used only for implementation of regX
  90.           dynstream.h    Interface file for dynstream class
  91.           bcstr.h        Interface file for BCstr class.  BCstr is compatible
  92.                          with the Borland object-based  container classes.  It
  93.                          is derived from str.
  94.  
  95.           str.cpp        Implementation file for str class
  96.           regX.cpp       Implementation file for regular expression class
  97.           dynstream.cpp  Implementation file for dynstream class
  98.           match.cpp      Regular expression compiling and searching routines
  99.           strsearch.cpp  Member functions relating to search/replace
  100.           bcstr.cpp      Implementation file for BCstr class
  101.           strcmp.cpp     Non-ansi string routines used by str class.  Add this
  102.                          to your library if your system does not have these
  103.                          (stricmp, strnicmp, strupr, strlwr).
  104.           grep.cpp       Demo program for "str" class, supporting file
  105.                          searching of regular expression matches.  Supports
  106.                          wildcard file specifications, case sensitivity, line
  107.                          numbers, etc.)
  108.  
  109.           makefile       This program defines how to build str.lib and
  110.                          grep.exe
  111.           readme         Brief overview
  112.  
  113.  
  114.  
  115. 1 GENERAL OVERVIEW AND DESIGN GOALS
  116. -----------------------------------
  117.  
  118. From the beginning this string class was designed to maximize usability and
  119. efficiency.  The following is a breakdown of some of the design objectives.
  120.  
  121. Composition:  One of the most common operations dealing with strings is to
  122. compose a string from other data.   The user would like to have the
  123. flexibility to naturally express how data is inserted into the composed
  124. string.  Class ostream from the iostream library has one of the most
  125. consistent and natural ways of transferring data I have yet seen.   Streams
  126. already provide all the functionality for converting built-in and user-defined
  127. types to a stream of char.  Thus complete interoperability with class
  128. "ostream" from the iostream library was a primary goal.
  129.  
  130. Efficiency through reference counting:  Every time you pass or return an
  131. object by value, a temporary copy is made of the original object.  Temporary
  132. object creation for string objects can be an expensive operation.  To increase
  133. the efficiency for making copies of "str" objects, reference counting should
  134. be used.  By using reference counting, temporary object creation becomes a
  135. very cheap operation.  Only a pointer is copied to create the new string,
  136. instead of allocating a new pointer, copying the character buffer, and then
  137. deallocating the pointer.
  138.  
  139. Efficiency through user-definable memory allocation:  Allocating and
  140. deallocating memory can be an expensive operation so it should be minimized.
  141. This should be handled by allocating a new data buffer only if the old buffer
  142. is too small to store the new data.  The user should be given the flexibility
  143. to define on an instance basis how much memory to allocate initially and when
  144. the string buffer overflows.
  145.  
  146. Search, replacement, and case sensitivity:  Searching and replacement of
  147. literal or regular expressions within a string should be supported. Searching
  148. should use the case sensitivity of the string being compared.  Case
  149. sensitivity should also extend to all the relational operators.
  150.  
  151.  
  152.  
  153. 2 INSTALLATION AND USE:  
  154. -------------------------
  155.  
  156.           2-1 STR.LIB
  157.           -----------
  158.           Type "make" to compile the source and create a library called
  159.           str.lib.  If you wish to place the object files in your own
  160.           library, insert the .obj files into your library.  You may also
  161.           want to place "str.h", and "regX.h" into your default include
  162.           path.  Bcstr.h is provided for those who wish to use the Borland
  163.           object-based container classes to store str's.
  164.  
  165.           If you are using Turbo C++ instead of Borland C++, edit the
  166.           makefile and substitute "TCC" for "BCC".
  167.  
  168.           Unix, Vax-Vms, and some other systems may also need to add
  169.           strcmp.obj to the library.  this module defines non-ansi string
  170.           routines used by the str class.  Add this to your library if your
  171.           system does not have these (stricmp, strnicmp, strupr, strlwr).
  172.           Do not add these to your library, if your system already defines
  173.           these (ie. Borland compilers).
  174.  
  175.             
  176.  
  177.           2-2 GREP
  178.           --------
  179.           Type make grep.exe to create the executable for grep.  Grep is
  180.           included as a demonstration program for the str class.  It
  181.           supports searching of literal and regular expressions within
  182.           files.  Wildcard file specifications, case sensitivity, line
  183.           numbers, etc. are all supported.  The implementation uses only
  184.           around 1 page of ode, which demonstrates how natural coding is
  185.           when using the regular expression capabilities of the string
  186.           class.
  187.  
  188.             
  189.  
  190.           2-3 UPGRADING
  191.           -------------
  192.           If you are upgrading from version 1, then you will need to
  193.           recompile all .cpp files that use the str class.  This must be
  194.           done since str.h has changed.  You also will need to change
  195.           occurrences of pad or strip to use the global versions.  This must
  196.           be done since the member functions pad and strip now modify their
  197.           object.  See section "Whats changed in 2.00".
  198.  
  199.             
  200.  
  201.           2-4 USING
  202.           ---------
  203.           You will need to include <str.h>, "str.h" in order to use class
  204.           str.  If you also wish to use regular expressions include
  205.           <regX.h>, "regX.h".  Header files "dynstream.h" and "regximp.h"
  206.           are strictly for implementation. and as such are separated into
  207.           other header file.  You should never reference them unless you
  208.           wish to modify their implementation, or derive a new class from
  209.           them.
  210.  
  211.             
  212.  
  213. 3 WHATS DIFFERENT ABOUT VERSION 2.0 - 2.2
  214. -----------------------------------------
  215.  
  216.  
  217.           3-0 WHATS DIFFERENT ABOUT VERSION 2.2
  218.           ---------------------------------
  219.  
  220.           Fixed substr assignment problem.  -->  str = substr
  221.           Add member function read, lowercase,
  222.           uppercase, and variations of pad and strip.
  223.  
  224.  
  225.           3-1 WHATS DIFFERENT ABOUT VERSION 2.1
  226.           -------------------------------------
  227.           Version 2.1 extends regular expression support to include context
  228.           sensitive regular expressions.  See section on regular expressions
  229.           for more details.
  230.             
  231.  
  232.           3-2 WHATS CHANGED IN 2.12
  233.           ------------------------------
  234.           Fix - substr assignment problem.  -->  str = substr
  235.           Fix - case sensitivity problem, member function index was backwards.
  236.  
  237.  
  238.           3-3 WHATS NEW IN 2.02 and 2.11
  239.           ------------------------------
  240.           Friend operator >> for reading in strings now directly uses the
  241.           string buffer, so as to remove the 256 character limit.
  242.  
  243.           Grep now supports files in other drives and directories.
  244.  
  245.           Optimizations to efficiency in str::_assign which is used
  246.           by many str member functions.
  247.             
  248.           Regular expression character sets can now contain octal characters.
  249.             
  250.           Fix - Member function "remove" now transfers only necessary 
  251.                 characters.  May have caused Windows application error
  252.                 previously.
  253.  
  254.  
  255. 4 WHATS DIFFERENT ABOUT VERSION 2.0
  256. -----------------------------------
  257.  
  258.           4-1 WHATS NEW IN 2.00
  259.           ---------------------
  260.  
  261.           1. Searching and replacing of character strings and regular
  262.              expressions.
  263.  
  264.           2. Case sensitivity now is a property of each instance of str.  All
  265.              searching and comparing for the str instance automatically
  266.              reflects its case sensitivity.  During comparisons between two
  267.              strings, the case sensitivity of the first argument is used.
  268.              Instances of str modify their case sensitivity through member
  269.              functions setCaseSensitive(int).
  270.             
  271.                {
  272.                   str a=("abcd efgh");
  273.                   a.setCaseSensitive(0);     // a is now case insensitive
  274.                   str b=("ABCD EFGH");
  275.                   cout << a.search("efGH");  // "1"   Found
  276.                   cout << b.search("efGH");  // "0"   Not found
  277.             
  278.                   cout << (a==b);         // "1"    Are equal
  279.                   cout << (b==a);         // "0"    Not equal
  280.                } 
  281.  
  282.           3. Miscellaneous optimizations and fixes.
  283.  
  284.  
  285.           4-2 WHATS GONE IN 2.00
  286.           ----------------------
  287.           Member function iindex is not directly supported.  Instead use
  288.           member function setCaseSensitive(int) to tell a string instance if
  289.           its searching and comparing should be case sensitive or not.  The
  290.           default is case sensitive.
  291.  
  292.  
  293.  
  294.           4-3 WHATS CHANGED IN 2.00
  295.           -------------------------
  296.           Member functions pad and strip now modify their object.  Use
  297.           global functions pad and strip to just return a value.   These
  298.           funtions were changed so that there would be a consistency among
  299.           member functions.  If the member function makes sense to modify
  300.           its object, then it will.  I apologize for those of you who will
  301.           have to change your code to reflect this.  But your code will be
  302.           more readable after you make the modifications.  You'll have to
  303.           change occurrences such as the following.
  304.  
  305.                
  306.  
  307.                Old Way                New Way
  308.                ------------------     ------------------
  309.                str a="abc";           str a = "abc";
  310.                str b = a.pad(10);     str b = pad(a, 10);
  311.  
  312.                
  313.  
  314. 5 SEARCHING/REPLACING
  315. ---------------------
  316.  
  317.           Member functions index, search, replace, and replaceAll are
  318.           provided to find and replace user-defined patterns.  There are
  319.           various forms of each, and can be summarized as follows.
  320.  
  321.           ------------------------------------------------------------------
  322.  
  323.             int index( pattern   [,matchLen]   [,start] );
  324.  
  325.             Find the next occurrence of pattern in this string.
  326.             Returns position where match occurs or -1 if not match is found.
  327.  
  328.             pattern:  pattern can be either a (const char *) or a regX.
  329.  
  330.             matchLen: Only allowed if pattern is a regX.  matchLen is the
  331.                       address of a str where the length of the match is saved.
  332.                       Optional Field.
  333.  
  334.             start:    Can be either a (int *) or an (int).  If it is an (int),
  335.                       then its used to determine where the search is to begin.
  336.                       If it is an (int *) then its used to determine where the
  337.                       search is to begin, and its updated to the position 
  338.                       where the match is found.  Optional Field where the 
  339.                       default is to start at the beginning of the string.
  340.  
  341.  
  342.           ------------------------------------------------------------------
  343.  
  344.             int search( pattern   [,matchPtr]   [,start] );
  345.  
  346.             Find the next occurrence of pattern in this string.
  347.             Returns true if match is found.
  348.  
  349.             pattern:  pattern can be either a (const char *) or a regX.
  350.  
  351.             matchPtr: Only allowed if pattern is a regX.  matchPtr is the
  352.                       address of a str where the match is saved.  
  353.                       Optional Field.
  354.  
  355.             start:    Can be either a (int *) or an (int).  If it is an (int),
  356.                       then its used to determine where the search is to begin.
  357.                       If it is an (int *) then its used to determine where the
  358.                       search is to begin, and its updated to the position 
  359.                       where the match is found.  Optional Field where the 
  360.                       default is to start at the beginning of the string.
  361.  
  362.             
  363.           ------------------------------------------------------------------
  364.  
  365.             int replace( pattern, replaceStr  [,start]   [,numReplace])
  366.  
  367.             Replace occurrences of pattern with replaceStr.
  368.             Returns number of actual replacements.
  369.  
  370.             pattern:    pattern can be either a (const char *) or a regX.
  371.  
  372.             replaceStr: pattern is replaced by replaceStr
  373.  
  374.             start:      Can be either a (int *) or an (int).  
  375.                         If it is an (int), then its used to determine where 
  376.                         the search is to begin.  If it is an (int *) then 
  377.                         its used to determine where the search is to begin, 
  378.                         and its updated to the position immediately after the
  379.                         location where the replacement occurred.  
  380.                         Optional Field where default is to start at the 
  381.                         beginning of the string.
  382.  
  383.             numReplace: Maximum number of replacements to perform.
  384.                         Optional Field where default is 1.
  385.  
  386.             
  387.           ------------------------------------------------------------------
  388.  
  389.             int replaceAll( pattern, replaceStr   [,start])
  390.  
  391.             Replace all occurrences of pattern with replaceStr
  392.             Returns number of actual replacements.
  393.  
  394.             pattern:    pattern can be either a (const char *) or a regX.
  395.  
  396.             replaceStr: pattern is replaced by replaceStr
  397.  
  398.             start:      Can be either a (int *) or an (int).  
  399.                         If it is an (int), then its used to determine where 
  400.                         the search is to begin.  If it is an (int *) then 
  401.                         its used to determine where the search is to begin, 
  402.                         and its updated to the position immediately after the
  403.                         location where the replacement occurred.  
  404.                         Optional Field where default is to start at the 
  405.                         beginning of the string.
  406.             
  407.           ------------------------------------------------------------------
  408.  
  409.  
  410. 6 REGULAR EXPRESSIONS
  411. ---------------------
  412.  
  413.           Regular expressions are a powerful form of searching and replacing
  414.           text.  Instead of pattern matching a literal character string,
  415.           they can match a more general pattern expression.  The regular
  416.           expression class obeys the following pattern rules.
  417.  
  418.           6-1 ONE CHARACTER PATTERN RULES:
  419.           --------------------------------
  420.  
  421.           1. All characters except ( " * + ? . [ ] & $ @ \" ) represent
  422.              themselves.  
  423.  
  424.           2. Special characters preceded by a backslash "\",  represent the
  425.              literal character.  However the following characters when
  426.              preceded by a backslash have special meaning.
  427.              
  428.                        \b        backspace
  429.                        \f        formfeed
  430.                        \n        newline
  431.                        \r        carriage return
  432.                        \t        tab
  433.                        \e        escape
  434.                        \s        space
  435.                        \^        control-character
  436.                        \xddd     character code in hex
  437.                        \ddd      character code in octal
  438.                        \         literal character code
  439.              
  440.  
  441.           3. Period represents any character, with the exception of new line.
  442.              Use [^] to cross line boundaries.
  443.  
  444.           4. Brackets, [ and ], enclose a set of characters.  The set of
  445.              character represents any one of its constituents, or any single
  446.              character not in the given sequence if the sequence starts with
  447.              ^.  Within the sequence, - between two characters denotes the
  448.              inclusive range.  For example, [a-z] represents any lower-case
  449.              letter, [^0-9] represents any non-digit character, [aeiou]
  450.              represents any vowel.
  451.             
  452.  
  453.           6-2 MULTI-CHARACTER PATTERN RULES
  454.           ---------------------------------
  455.  
  456.           1. If * follows a one character pattern, it indicates that the
  457.              previous pattern may appear arbitrarily often, or even not at all
  458.              (0 or more occurrences).
  459.  
  460.           2. If + follows one of these pattern parts, it indicates that the
  461.              previous character pattern appears at least once (1 or more
  462.              occurrences)
  463.  
  464.           3. If ? follows one of these pattern parts, it indicates that the
  465.              previous character pattern has zero or one occurrence.
  466.             
  467.  
  468.           6-3 ANCHORS FOR REGULAR EXPRESSION
  469.           ----------------------------------
  470.  
  471.           1. ^ at the beginning of a pattern represents the beginning of an
  472.              input line.      $ at the end of a pattern represents the end of
  473.              an input line.
  474.  
  475.           2. @ flags what part of the regular expression is actually part of
  476.              the match.  For example the regular expression "[0-9]+\.@[0-9]+"
  477.              will match the fractional part of a floating point number. More
  478.              details are described later.
  479.             
  480.  
  481.           6-4 AMBIGUITY RULES FOR SEARCHING AND REPLACING
  482.           -----------------------------------------------
  483.  
  484.           Chooses the pattern that represents the longest possible match.
  485.  
  486.           For instance consider the following example,
  487.  
  488.             
  489.                regX pattern("Numbers .*[0-9]+");
  490.                str a("Numbers 34,67");
  491.                a.search(pattern, &match);   // match = "Numbers 34,67
  492.  
  493.  
  494.           Both "Numbers 34,67" and "Numbers 34" match the pattern, but
  495.           "Numbers 34,67" is chosen since it is longer.
  496.  
  497.             
  498.  
  499.           6-5 CONTEXT SENSITIVE REGULAR EXPRESSIONS
  500.           -----------------------------------------
  501.  
  502.           Quite often one knows the context of what is being looked for, but
  503.           does not have any natural way of expressing this in a regular
  504.           expression format.  Consider the following problem.
  505.  
  506.           Problem:
  507.  
  508.               Write a program that parses a paragraph and removes the comma 
  509.               from all numbers of the form (ddd,ddd,...).  Commas used in 
  510.               any other context should not be affected.
  511.  
  512.           Solution:
  513.  
  514.               void RemoveNumberComma(str * buffer)
  515.               {
  516.                  regX commaInDigitX("[0-9]@,@[0-9]");
  517.                  buffer->replaceAll(commaInDigitX, "");
  518.               };
  519.             
  520.               str a("Hi, this is test number 3, and the year is 1,992.");
  521.               RemoveNumberComma(&a);
  522.             
  523.  
  524.           The above code replaces the number 1,992 with 1992.   The regular
  525.           expression commaInDigitX is context aware.   The user is not
  526.           forced to distinquish for himself if the comma is in a digit or
  527.           not.  Without context aware regular expresions, the above problem
  528.           is more difficult.  The programmer would be required to search for
  529.           a comma, and then check the next and previous characters to see if
  530.           they were a digit before performing the replacement.
  531.  
  532.  
  533.           Here is another example.
  534.  
  535.             
  536.             regX AuthorX("Please register by sending $15 to @[A-Za-z\\s]+$");
  537.             str registration("Please register by sending $15 to Roy S. Woll");
  538.             str author;
  539.             registration.search(AuthorX, &author);   // author = "Roy S. Woll"
  540.  
  541.             
  542.  
  543.           6-6 REGULAR EXPRESSION EXAMPLES:
  544.           --------------------------------
  545.             
  546.             {  
  547.             
  548.                regX number("[0-9]+");
  549.                regX anyWhiteSpace("[\t\\s]+");
  550.                regX leadingWhiteSpace("^[\t\\s]+");
  551.             
  552.             //
  553.             // replacement
  554.             //
  555.                str a("This year is 1992");
  556.                a.replace( number, "1993");      // a = "This year is 1993"
  557.             
  558.                a = "     \tA great string class";
  559.                a.replace( leadingWhiteSpace, "");// a = "A great string class"
  560.             
  561.                a = "A  great    string  \t class";
  562.                a.replaceAll( anyWhiteSpace, " ");// a = "A great string class"
  563.             
  564.             //
  565.             // searching
  566.             //
  567.                str match;
  568.                a = "This year is 1992";
  569.                if (a.search(number))         // "found"
  570.                   cout << "found" << endl;
  571.             
  572.                a.search(number, &match)      // match = "1992"
  573.             
  574.                a = "My wife was born on April 12, 1968.";
  575.                int pos=0;
  576.                a.search(number, &match, &pos);  // match = "12";
  577.                pos+=match.length();
  578.                a.search(number, &match, &pos);  // match = "1968";
  579.             
  580.             }
  581.  
  582.  
  583.           6-7 OPTIMIZATION HINTS FOR REGULAR EXPRESSIONS
  584.           ----------------------------------------------
  585.           Since regular expression compilation (during construction or
  586.           assignment) is a relatively slow operation, you should try to
  587.           minimize them by declaring them as static if at all possible..  In
  588.           this way they will only be compiled once.  
  589.  
  590.             
  591. 7 MEMORY ALLOCATION CONTROL
  592. ---------------------------
  593.  
  594.           To reduce the overhead of continually creating and destroying str
  595.           objects, the str class allows the user to customize how much
  596.           memory to allocate initially and when the string buffer is full.
  597.           The original buffer is used until an operation causes it to grow
  598.           beyond its original size.  The new size is the original size plus
  599.           the increment size.  For example consider the following code
  600.           fragment.
  601.  
  602.              {
  603.                str example2("abcdefg", 10, 15);
  604.                // An instance of str is defined to contain "abcdefg".  
  605.                // Its initial buffer size is 10 characters, and it grows 
  606.                // by 15 bytes when it needs to expand.  
  607.             
  608.                example2 = "123";
  609.                // Assign "123" to example2.  No memory reallocation 
  610.                // is necessary since the new contents still fit in 
  611.                // the original buffer.
  612.             
  613.                example2 = "0123456789012";
  614.                // Assign "0123456789012" to example2.  Memory reallocation is 
  615.                // necessary since the new contents exceed the original size of
  616.                // ten characters.  This assignment causes a new buffer
  617.                // to be created that supports (10+15) bytes.
  618.              }
  619.             
  620.           The Default value for the initial memory allocation size is the
  621.           length of the first value being stored.  The Default value for the
  622.           memory expansion increment is 256 characters. If you'd rather have
  623.           the string truncate rather than expand, use an increment of 0.  If
  624.           you would like to change the default, then edit the str.h file and
  625.           modify the constant str_default_memincr.
  626.  
  627.  
  628.  
  629. 8 INTEROPERABILITY WITH OSTREAM
  630. -------------------------------
  631.  
  632.           Of primary importance in the design of the class was to allow
  633.           complete interoperability with class "ostream" from the iostream
  634.           library.  Class "str" supports all the ostream operations,
  635.           including complete usage of the I/O manipulators.  Streams already
  636.           provide all the functionality for converting built-in and
  637.           user-defined types to a stream of char.  Rather then trying to
  638.           duplicate this, the str class works with the  stream class.
  639.  
  640.           For example, the following module takes 3 integers and returns a
  641.           time specification into a string of the format "hh:mm:ss".
  642.  
  643.              
  644.  
  645.                str getTimeStr(int hour, int minute, int second)
  646.                {
  647.                   str timestr;
  648.                   timestr.stream()  << setfill('0') << setw(2) << hour
  649.                      << ":" << setfill('0') << setw(2) << minute
  650.                      << ":" << setfill('0') << setw(2) << second;
  651.                   return timestr;
  652.                };
  653.             
  654.  
  655.           This method has significant advantages over class "ostrstream".
  656.           Class "ostrstream" has the disadvantages of not being
  657.           interchangeable with "const char *", not having control over
  658.           memory allocation/reallocation, and not supporting string
  659.           operators and member functions.  I also found it significantly
  660.           more cumbersome to use.
  661.  
  662.           Class "str" gives the user full access to ostream's capabilities,
  663.           while maintaining consistency with the str's buffer.
  664.  
  665.             
  666.  
  667. 9 REFERENCE COUNTING
  668. --------------------
  669.  
  670.           To increase the efficiency for making a copy of a "str" object,
  671.           reference counting is used.  You may think you rarely make copies
  672.           of str objects, but that is probably not the case.  Every time you
  673.           pass or return an object by value, a temporary copy is made of the
  674.           original object.  Temporary object creation for string objects can
  675.           be an expensive operation.  
  676.  
  677.           By using reference counting, temporary object creation becomes a
  678.           very cheap operation.  Only a pointer is copied to create the new
  679.           string, instead of allocating a new pointer, copying the character
  680.           buffer, and then deallocating the pointer.
  681.  
  682.             
  683.           For example:
  684.             
  685.                   {
  686.             
  687.             (1)         str a = "just some string   ";
  688.             (2)         str b = a;                     
  689.             
  690.             (3)         str c = a + b;               
  691.             (4)         str c = strip(a);
  692.             
  693.                   }
  694.             
  695.  
  696.  
  697.           Statement (1) creates a str object containing "just some string".
  698.           Statement (2) copies a to b.  With reference counting only a
  699.           pointer is copied.  Without reference counting all the character
  700.           data is transferred.  In statement (3) a temporary str object is
  701.           returned by (a+b) and copied to c.  Using reference counting only
  702.           the pointer for the temporary is copied,  instead of the whole
  703.           character buffer.  Statement (4) is just like statement (3) where
  704.           strip(a) returns a temporary which is copied to c.
  705.  
  706.           However reference counting itself can present some efficiency
  707.           problems.  The popular scheme of having a reference pointer, and a
  708.           data pointer has the disadvantage of slowing down operations for
  709.           singly referenced objects.  This is caused by the need to allocate
  710.           two unique pointers, and the extra level of indirection when
  711.           accessing the character buffer.
  712.  
  713.           The "str" class uses a single pointer that points to block that
  714.           contains both the reference data and the character data.  In this
  715.           way at most one memory allocation is done per operation, making
  716.           the execution times for creating singly referenced objects
  717.           comparable to classes that don't use reference counting. 
  718.  
  719.  
  720. STR REFERENCE
  721. constructor str(void); 
  722.  
  723.             Construct a str where the memory allocation is determined by the
  724.             first assignment to the instance, and then it grows  by
  725.             str_default_memincr.
  726.  
  727.             
  728.  
  729. constructor str(int bufsize, int memincr= str_default_memincr);
  730.  
  731.             Construct a str that allocates a (bufsize) byte buffer during the
  732.             first assignment, and thereafter grows by  (memincr) bytes when
  733.             buffer is full.
  734.  
  735.             
  736.  
  737. constructor str(const char * s, int bufsize=0, memincr=str_default_memincr);
  738. constructor str(const str& s, int bufsize=0, memincr=str_default_memincr);
  739.  
  740.             Construct a str containing (s). It allocates a (bufsize) byte
  741.             buffer during the first  assignment (or the length of (s) if
  742.             larger than bufsize), and thereafter grows by (memincr) bytes when
  743.             the buffer is full.  Use (memincr=0) to prevent the string from
  744.             growing.
  745.  
  746.             
  747.             Constructor examples:
  748.             
  749.             //
  750.             // Memory allocation determined by first assignment 
  751.             // to instance, and then grows by str_default_memincr. 
  752.             //
  753.                str mystr; 
  754.             
  755.             //
  756.             // Defines 10 instances of str. 
  757.             // Memory allocation determined by first assignment 
  758.             // to instance, and then grows by str_default_memincr. 
  759.             //
  760.                str str_array[10];  
  761.             
  762.             // 
  763.             // Define str containing "Some demo text"  100 byte buffer space 
  764.             // allocated, and then grows by 200 bytes when buffer is full. 
  765.             //
  766.                str mystr("Some demo text", 100, 200);
  767.             
  768.             //
  769.             // Define (mystr2) to contain substr formed from four characters 
  770.             // of (mystr1) starting at position 1. 
  771.             // mystr2 will contain "trin" 
  772.             //
  773.                str mystr1("string 1");
  774.                str mystr2(mystr1(1,4)); // "trin" 
  775.             
  776.             //
  777.             // Define str AnotherStr containing mystr 
  778.             //
  779.                str AnotherStr(mystr);  
  780. MEMBER FUNCTION
  781. OPERATORS
  782.  
  783. const char *  operator const char * () const;   
  784.  
  785.             Return pointer to this str's character buffer.  Compiler will
  786.             automatically call this when a cast to a (const char*) is
  787.             necessary.  Instances of  str can be used interchangeably with
  788.             const  char *.
  789.  
  790.             
  791.  
  792.             For example, when using the ansi C str library.  
  793.             //
  794.             // find location of "234" in MyString 
  795.             //
  796.             // foundptr = "2345 012345"
  797.             //
  798.                str MyString("012345 012345"); 
  799.                char * foundptr = strstr(MyString, "234"); 
  800.             
  801.             
  802.             //
  803.             // However you will not be allowed to use str  
  804.             // interchangeably with (char *). 
  805.             //
  806.                str MyString("012345"); 
  807.                strcpy(MyString, "hello");  //compiler type-checking error. 
  808.             
  809.             
  810. ()          const char * operator()() const; 
  811.  
  812.             Return pointer to this str's character buffer.
  813.  
  814.             
  815.  
  816. (int)       operator()(int index) const; 
  817.  
  818.             Return pointer to this str's character buffer starting  at
  819.             position (index).
  820.  
  821.             
  822.             //
  823.             // find location of "234" in MyString starting at offset 5
  824.             //
  825.             // foundptr = "2345"
  826.             //
  827.                str MyString("012345 012345"); 
  828.                char * foundptr = strstr(MyString(5), "234"); 
  829.             
  830.             
  831.  
  832. (int,int)   substr operator()(int pos, int num); 
  833.  
  834.             Substr operations supported using (int,int) notation. This member
  835.             function has two uses.  It can be used to  extract a substring
  836.             from a given string by using it on the right-hand-side of an
  837.             expression.  It extracts (num) characters starting at offset (pos)
  838.             of the string.  For example the following code fragment
  839.             concatenates two substrings.
  840.  
  841.             
  842.              {  
  843.                str myString("abdefghijklmnopqrstuvwxyz");
  844.                cout << myString(0,3) + myString(23,3); // "abcxyz";  
  845.              }
  846.             This member function can also be used to assign a selected region
  847.             of a string when used on the left-hand-side of an expression.  It
  848.             replaces (num) characters starting at offset (pos) of the string
  849.             with the left-hand-side of an  expression.
  850.  
  851.             For example, the following code fragment replaces "test"  with
  852.             "survey" by using a substr operation.
  853.  
  854.             
  855.  
  856.              {
  857.                str test_substr1("This is a test");  
  858.                int pos = test_substr1.index("test");
  859.                if (pos>=0) test_substr1(pos, 4) = "survey"; 
  860.              }
  861.             
  862.  
  863.  
  864. []          operator char& operator[](int position);
  865.  
  866.             Return reference to character buffer at offset position.
  867.  
  868.             
  869.             Example []:
  870.             //
  871.             //  Can access str as an array of char for assignment purposes. 
  872.             //
  873.                str MyString("012345"); 
  874.                MyString[4]='0';        // MyString = "012305"
  875.             
  876.             
  877. []          operator char operator[](int position) const;
  878.  
  879.             Return character at offset position of character buffer. This
  880.             version is only called if the calling str object is a constant
  881.             object.  It is provided because it is significantly faster than
  882.             the non-const version of operator [].
  883.  
  884.             
  885.             Example []:
  886.             //
  887.             //  Can access str as an array of char for retrieval purposes.
  888.             //
  889.                const str MyString("012345"); 
  890.                cout << MyString[4];  // writes '4' to screen
  891.             
  892.             
  893. =           str & operator = (const str & s);     // s = str;
  894.             str & operator = (const substr & s);  // s = substr;
  895.             str & operator = (const char * s);    // s = charptr
  896.             str & operator = (const char s);      // s = character
  897.  
  898.             Assign (s) to this str.
  899.  
  900.  
  901.  
  902.             Example:
  903.             
  904.              {
  905.                str s,t;
  906.                t = 'a';    // t = "a"
  907.                t = "abc";  // t = "abc"
  908.                s = t;      // s = "abc"
  909.                s = t(1,2); // s = "bc"
  910.              };
  911.             
  912.             
  913. +=          str & operator += (const str & s);  // s += str
  914.             str & operator += (const char * s); // s += charptr
  915.             str & operator += (const char s); // s += char
  916.  
  917.             Concatenate (s) to this str
  918.  
  919.  
  920.  
  921.             Example:
  922.             
  923.              {
  924.                str s;
  925.                str t="123";
  926.                s += 'a';      // s = "a"
  927.                s += "abc";    // s = "aabc"
  928.                s += t;     // s = "aabc123"
  929.                s += t(1,2);   // s = "aabc12323"
  930.              };
  931.             
  932.  
  933. <<          str & operator << (const char * s); // s << charptr
  934.             str & operator << (const str& s); // s << str
  935.             str & operator << (const int s);  // s << int
  936.             str & operator << (const char s); // s << char
  937.  
  938.             Concatenate (s) to this str.  Operator "<<" is only provided
  939.             because it has a more natural associativity (left to right) than
  940.             operator "+=" when concatenating a series.
  941.  
  942.             
  943.             Examples:
  944.              {
  945.                str s;
  946.                str t="123";
  947.                int i=99;
  948.                s << 'a';      // s = "a"
  949.                s << "abc"; // s = "aabc"
  950.                s << t;     // s = "aabc123"
  951.                s << i;     // s = "aabc12399"
  952.                s << t(1,2);   // s = "abbc1239923"     
  953.              };
  954.             
  955.              {
  956.                str testconcat1(" there in ");
  957.                int year = 1992;
  958.                str test;
  959.                test << "hello" << testconcat1 
  960.                   << year << '.';      // test = hello there in 1992.
  961.              }
  962.             
  963.             
  964. +           str operator+(const str &) const;
  965.             str operator+(const substr &) const;
  966.             str operator+(const char * b) const;
  967.             str operator+(const char b) const;
  968.             friend str operator+(const char *, const str &); 
  969.  
  970.             Concatenate s1 and s2 and return the result.  
  971.  
  972.             
  973.             {
  974.                str a("123");
  975.                str s = a + "abc";      // s = "123abc"
  976.             }
  977.             
  978.             Notes on efficiency:  For optimal perfomance, avoid cascading
  979.             operator "+" since temporary objects will be created.  Use
  980.             operators "+=",  "<<" , or the stream() member function.  Operator
  981.             "+=" and "<<" are more efficient than stream(), since stream()
  982.             must create an instance of dynstream the first time it is used,
  983.             but they are not as flexible or convenient.  
  984.  
  985.             
  986.  
  987. FRIEND/GLOBAL
  988. FUNCTION OPERATORS
  989.             
  990.  
  991. ==,!=,<=    int operator==(const str & s1, const str & s2)
  992. >=,<,>      Equal to, not equal to, less than, etc. relational operators
  993.             supported.  Comparison of s1 and s2 is determined by the case
  994.             sensitivity of s1.
  995.  
  996.  
  997.             Example for relational operators:
  998.             //
  999.             // The following code fragment will yield an output of 
  1000.             // "010101", signifying false, true, false, true, false, true.
  1001.             //
  1002.                str a("abc");
  1003.                str b("def");
  1004.                cout << (a == b);
  1005.                cout << (a != b);
  1006.                cout << (a >= b);
  1007.                cout << (a <= b);
  1008.                cout << (a > b);
  1009.                cout << (a < b);
  1010.  
  1011. MEMBER
  1012. FUNCTIONS
  1013.  
  1014. assign      str & assign (const char * source, int len)
  1015.  
  1016.             Assign (len) characters from (source) to this str.
  1017.  
  1018.             Example:
  1019.  
  1020.             
  1021.                str a;
  1022.                str b="0123456789";
  1023.                a.assign(b(5), 5);   // a = "56789";
  1024.             
  1025.  
  1026. caseSensitive int caseSensitive(void) const;
  1027.  
  1028.             Returns the case sensitivity for the current str object.
  1029.  
  1030.             
  1031.  
  1032. index       int index(const char * s, int start=0) const;
  1033.  
  1034.             Search this str for character string (s) and return the offset
  1035.             where a match occurs.  Search starts at offset (start).   Return
  1036.             -1 if no match is found.  Case sensitivity is determined by this
  1037.             str instance.  Case is sensitive by default when the str is
  1038.             created, but can be overridden through member  function
  1039.             setCaseSensitive(int).
  1040.  
  1041.             
  1042.  
  1043. index       int index(const regX& reg, int start=0) const;
  1044.  
  1045.             Search this str for regular expression (reg) and return the offset
  1046.             where a match occurs.  Search starts at offset (start).   Return
  1047.             -1 if no match is found.  
  1048.  
  1049.             
  1050.             //
  1051.             // Search for the first floating point number
  1052.             //
  1053.             //    pos = 20
  1054.             //
  1055.             
  1056.              {
  1057.                regX floatingPointNumber ("[0-9]+[.][0-9]+");
  1058.                str a = "pi is approximately 3.14159265";
  1059.                int pos = a.index(floatingPointNumber);
  1060.              }
  1061.             
  1062. index       int index(const regX& reg, int * matchLen, int start=0) const;
  1063.  
  1064.             Same as index(const regular&, int) but returns the length of the
  1065.             matched string in *matchLen.
  1066.  
  1067.             
  1068.             //
  1069.             // Search for the first floating point number
  1070.             //
  1071.             //    pos = 20
  1072.             //    matchlen = 10
  1073.             //
  1074.             
  1075.              {
  1076.                regX floatingPointNumber ("[0-9]+[.][0-9]+");
  1077.                str a = "pi is approximately 3.14159265";
  1078.                int matchlen;
  1079.                int pos = a.index(floatingPointNumber, &matchlen);
  1080.              }
  1081.             
  1082.             
  1083. insert      int insert(int pos, char ch);
  1084.  
  1085.             Insert char (ch) starting at offset (pos) of this str.  Insertion
  1086.             can fail if the str is already full, and the str is not allowed to
  1087.             expand (constructed with memincr=0).
  1088.  
  1089.             
  1090.              {
  1091.                a = "abcdefghi";
  1092.                a.insert(5, '1');    // a = "abcde1fghi"
  1093.              }
  1094.  
  1095.  
  1096. insert      int insert(int pos, const char * insertStr); 
  1097.  
  1098.             Insert character buffer insertStr starting at offset (pos) of this
  1099.             str.  Insertion can fail if the insertStr would cause this str to
  1100.             overflow, and the str is not allowed to expand (constructed with
  1101.             memincr=0).
  1102.  
  1103.             
  1104.              {
  1105.                a = "abcdefghi";
  1106.                a.insert(5, "12");    // a = "abcde12fghi"
  1107.              }
  1108.             
  1109.             
  1110. length      int length(void) const;  
  1111.  
  1112.             Return current string length of buffer.
  1113.  
  1114.             
  1115.              {
  1116.                str MyString("abc");
  1117.                cout << MyString.length();   // writes 3 to screen.
  1118.              }
  1119.             
  1120.             
  1121. pad         str& pad(int padsize, int t=right, char padchar = ' ');
  1122.  
  1123.             Pad (padchar) characters to the right and/or left of this str
  1124.             yielding a string of length (padsize).   The original string is
  1125.             modified.  The padtype can be one of (right, left, or both).  
  1126.  
  1127.             
  1128.             
  1129.             //
  1130.             // This code performs the following.
  1131.             //
  1132.             //    a = "hello there                     "
  1133.             //    a = "*********************hello there"
  1134.             //    a = "          hello there           "
  1135.             //
  1136.             //
  1137.             
  1138.                str a("hello there");
  1139.                a.pad(32);
  1140.             
  1141.                a = "hello there";
  1142.                a.pad(32, str::left,'*');
  1143.             
  1144.                a = "hello there";
  1145.                a.pad(32, str::both);
  1146.             
  1147.             
  1148. remove      void remove(int pos, int numdel=1); 
  1149.  
  1150.             Remove (numdel) characters starting at position (pos) of this str.
  1151.  
  1152.             
  1153.              {
  1154.                a = "abcdefghi";
  1155.                a.remove(5, 2);   // a = "abcdehi"
  1156.              }
  1157.  
  1158.  
  1159. replace     int replace(const regX& reg, const char * replaceStr, int
  1160.             start=0, int numReplacements=1);
  1161.  
  1162.             Replace occurrences of the pattern (reg) with (replaceStr).
  1163.             Replacement begins at offset (start) of this string, and at most
  1164.             (numReplacements) replacements are performed.  The number of
  1165.             actual replacements is returned.
  1166.  
  1167.             
  1168.             //
  1169.             // Replace first occurance of whitespace with a single blank
  1170.             //
  1171.             // a = "A great   string class"
  1172.             //
  1173.              regX whiteSpace("[\t ]+");
  1174.              str a = "A  \t  great   string class";
  1175.              a.replace(whiteSpace," ");
  1176.             
  1177.             
  1178. replace     int replace(const regX& reg, const char * replaceStr,       int*
  1179.             startPtr, int numReplacements=1);
  1180.  
  1181.             Replace occurrences of the regular expression (reg) with
  1182.             (replaceStr).  Replacement begins at offset (*startPtr) of this
  1183.             string, and at most (numReplacements) replacements are performed.
  1184.             The number of actual replacements is returned.  (*startPtr) is
  1185.             updated to begin after the matched pattern or set to -1 if no
  1186.             match found.
  1187.  
  1188.             
  1189.             //
  1190.             // Replace all whitespace with a single blank.
  1191.             //
  1192.             // a = "A great string class"
  1193.             //
  1194.                regX whiteSpace("[\t ]+");
  1195.                str a = "A    great    string  \t class";
  1196.             
  1197.                int pos=0;
  1198.                while (a.replace(whiteSpace, " ", &pos));
  1199.             
  1200.             
  1201. replace     int replace(const char * pattern, const char * replaceStr,
  1202.             int start=0, int numReplacements=1);
  1203.  
  1204.             Replace occurrences of the character string (pattern) with
  1205.             (replaceStr).  Replacement begins at offset (start) of this
  1206.             string, and at most (numReplacements) replacements are performed.
  1207.             The number of actual replacements is returned.
  1208.  
  1209.             
  1210.             //
  1211.             // Replace 2 occurrences of "/" with " " starting at pos 3
  1212.             //
  1213.             // a = "A/great string class"
  1214.             //
  1215.                str a = "A/great/string/class";
  1216.                int pos=0;
  1217.                a.replace("/", " ", 3, 2);
  1218.             
  1219.             
  1220. replace     int replace(const char * pattern, const char * replaceStr,
  1221.             int * startPtr, int numReplacements=1);
  1222.  
  1223.             Replace occurrences of the character string (pattern) with
  1224.             (replaceStr).  Replacement begins at offset (start) of this
  1225.             string, and at most (numReplacements) replacements are performed.
  1226.             The number of actual replacements is returned.   (*startPtr) is
  1227.             updated to begin after the matched pattern or set to -1 if no
  1228.             match found.
  1229.  
  1230.             
  1231.             //
  1232.             // Replace all occurrences of "/" with " "
  1233.             //
  1234.             // a = "A great string class"
  1235.             //
  1236.                a = "A/great/string/class";
  1237.                int pos=0;
  1238.                while (a.replace("/", " ", &pos));
  1239.             
  1240.             
  1241. replaceAll  int replaceAll(const char * pattern, const char * replaceStr,
  1242.                   int pos=0);
  1243.  
  1244.             Replace all occurrences of the character string (pattern) with
  1245.             (replaceStr).  Replacement begins at offset (start) of this
  1246.             string.   The number of actual replacements is returned.
  1247.  
  1248.             
  1249.             //
  1250.             // Replace all occurrences of "!" with " "
  1251.             //
  1252.             // a = "A great string class"
  1253.             //
  1254.                str a = "A!great!string!class";
  1255.                a.replaceAll("!", " ");
  1256.             
  1257.             
  1258. replaceAll  int replaceAll(const regX& reg, const char * replaceStr,
  1259.             int pos=0);
  1260.  
  1261.             Replace all occurrences of the regular expression (erg) with
  1262.             (replaceStr).  Replacement begins at offset (start) of this
  1263.             string.   The number of actual replacements is returned.
  1264.  
  1265.             
  1266.             //
  1267.             // Replace all whitespace with a single blank
  1268.             //
  1269.                regX whiteSpace("[\t ]+");
  1270.                str a = "A    great    string  \t class";
  1271.                a.replaceAll(whiteSpace," "); // a = "A great string class"
  1272.  
  1273.  
  1274. search      int search(const char * pattern, int *startPtr) const;
  1275.  
  1276.             Search for the character string (pattern) and return 1 if
  1277.             (pattern) is found.  Searching begins at offset (*startPtr) of
  1278.             this string.  (*startPtr) is updated to the starting position of
  1279.             the match or set to -1 if no match is found.
  1280.  
  1281.             
  1282.              {
  1283.                str a = "I love snow. God is love.";
  1284.                str love = "love";
  1285.                int pos = 0;
  1286.                if (a.search(love, &pos))     // pos = 2
  1287.                   cout << "there is love";   // "there is love"
  1288.                pos+= love.length();
  1289.                if (a.search(love, &pos))     // pos = 20
  1290.                   cout << "there is more love"; // "there is more love"
  1291.              }
  1292.             
  1293.             
  1294. search      int search(const char * pattern, int start=0) const;
  1295.  
  1296.             Search for the character string (pattern) and return 1 if
  1297.             (pattern) is found.  Searching begins at offset (start) of this
  1298.             string.  
  1299.  
  1300.             
  1301.              {
  1302.                str a = "I love snow";
  1303.                if (a.search("love"))
  1304.                   cout << "there is love";   // "there is love"
  1305.              }
  1306.  
  1307.  
  1308. search      int search(const regX& reg, int *startPtr) const;
  1309.  
  1310.             Search for the regular expression reg in this string and return 1
  1311.             if (reg) is found.  Searching begins at offset (*startPtr) of this
  1312.             string.  (*startPtr) is updated to the starting position of the
  1313.             match, or -1 if no match is found.  
  1314.  
  1315.             
  1316.              {
  1317.                regX number("[0-9]+");
  1318.                str a = "John 3:16";
  1319.                int pos=0;
  1320.                a.search(number, &pos);   // pos = 5;
  1321.              }
  1322.             
  1323.             
  1324. search      int search(const regX& reg, int start=0) const;
  1325.  
  1326.             Search for the regular expression reg in this string and return 1
  1327.             if (reg) is found.  Searching begins at offset (start) of this
  1328.             string.  
  1329.  
  1330.             
  1331.  
  1332.              {
  1333.                regX number("[0-9]+");
  1334.                a = "John 3:16";
  1335.                if (a.search(number))
  1336.                   cout << "found number";  // "found number"
  1337.              }
  1338.  
  1339.  
  1340. search      int search (const regX&, str * matchPtr=0, int start=0) const;
  1341.  
  1342.             Search for the regular expression reg in this string and return 1
  1343.             if (reg) is found. Searching begins at offset (start) of this
  1344.             string.  The matched pattern is saved as (*matchPtr).
  1345.  
  1346.             
  1347.              {
  1348.                regX number("[0-9]+");
  1349.                str a = "Bobby Fisher: world champion in 1993?"
  1350.                str match;
  1351.                a.search(number, &match);  // match = "1993"
  1352.              }
  1353.             
  1354.             
  1355. search      int search(const regX& reg, str* matchPtr,      int* startPtr)
  1356.             const;
  1357.  
  1358.             Search for the regular expression reg in this string and return
  1359.             0/1 if (reg) is found/not found.  Searching begins at offset
  1360.             (*startPtr) of this string.  (*startPtr) is updated to the
  1361.             starting position of the match, or -1 if not match is found.  The
  1362.             matched pattern is saved as (*matchPtr).
  1363.  
  1364.             
  1365.              {
  1366.                regX number("[0-9]+");
  1367.                str month, day, year;
  1368.                str a = "My wife's birthday is 4/12/1968.";
  1369.                int pos=0;
  1370.                a.search(number, &month, &pos);   // month = "4";
  1371.                pos+= month.length();
  1372.                a.search(number, &day, &pos);    // day = "12";
  1373.                pos+= day.length();
  1374.                a.search(number, &year, &pos);      // year = "1968";
  1375.              }
  1376.  
  1377. size        int size(void) const;    
  1378.  
  1379.             Return current size of memory allocated for buffer.
  1380.  
  1381.             
  1382.              {
  1383.                str MyString("abc", 80);
  1384.                cout << MyString.size();   // writes 80 to screen.
  1385.              }
  1386.             
  1387.             
  1388. setCaseSensitive  void setCaseSensitive(int val);
  1389.  
  1390.             Set the case sensitivity for the current str object.  If (val) is
  1391.             0 then string comparisons and searches will not be case sensitive.
  1392.             If (val) is 1 then they will be case sensitive.
  1393.  
  1394.             
  1395.  
  1396. stream      ostream& stream(void);
  1397.  
  1398.             Return ostream for this str.  Consult your iostream documentation
  1399.             for details on using an ostream.
  1400.  
  1401.             
  1402.             Examples stream():
  1403.             //
  1404.             // getTimeStr() converts a time specification into a string of 
  1405.             // the format "hh:mm:ss" using leading zeros.
  1406.             //
  1407.                str getTimeStr(int hour, int minute, int second)
  1408.                {
  1409.                   str timestr;
  1410.                   timestr.stream() << setfill('0') << setw(2) << hour
  1411.                      << ":" << setfill('0') << setw(2) << minute
  1412.                      << ":" << setfill('0') << setw(2) << second;
  1413.                   return timestr;  
  1414.                };
  1415.             
  1416.             //
  1417.             // Use stream operation to concatenate two strings.
  1418.             //
  1419.                str a;
  1420.                a.stream() << "Hello there."; // a = "Hello there"
  1421.                a.stream() << " Goodbye." // a = "Hello there. Goodbye."
  1422.             
  1423.                
  1424. stream      ostream& stream(int p);
  1425.  
  1426.             Return ostream for this str and move the ostream put pointer to
  1427.             offset (p).  Same functionality as stream(void) except that the
  1428.             user can change the stream put pointer.
  1429.  
  1430.             
  1431.  
  1432.             Example stream(int):
  1433.             
  1434.                str a;
  1435.                a.stream()  << "Hello there.";   // a = "Hello there."
  1436.                a.stream(0) << "Hello again.";   // a = "Hello again."
  1437.             
  1438.             
  1439. strip       str& strip(int striptype=trailing, const char * stripchars= "
  1440.             \t");
  1441.  
  1442.             Strip leading and/or trailing characters from the str and return
  1443.             the resulting str.  The original string is modified.  The strip
  1444.             type (striptype) can be one of (leading, trailing, or both).
  1445.             (stripchars) is a character string that contains a set of
  1446.             characters to strip.  The default is to strip trailing spaces and
  1447.             tabs.
  1448.  
  1449.             
  1450.             Example strip:
  1451.             
  1452.                str origstr("********hello there        ");
  1453.                str a = origstr;  
  1454.                a.strip();        // a = "********hello there        "
  1455.             
  1456.                a = origstr;
  1457.                a.strip(str::leading,"*"); // a = "hello there        "
  1458.             
  1459.                a = origstr;
  1460.                a.strip(str::both," *");   // a = "hello there"
  1461.             
  1462.  
  1463.             
  1464. strip       str& strip(int striptype=trailing, char stripchar);
  1465.  
  1466.             Strip leading and/or trailing characters (as defined by stripchar)
  1467.             from the str and return the resulting str.  The original string is
  1468.             modified.  The strip type (striptype) can be one of (leading,
  1469.             trailing, or both).
  1470.  
  1471.             
  1472.             //
  1473.             // This code performs the following.
  1474.             //
  1475.             //    a = "********hello there"
  1476.             //    a = "hello there"
  1477.             //
  1478.                str a("********hello there        ");
  1479.                a.strip(str::trailing,' ');
  1480.                a.strip(str::leading,'*');
  1481.  
  1482.  
  1483.  
  1484. FRIEND/GLOBAL
  1485. FUNCTIONS
  1486.  
  1487.  
  1488. >>          friend istream& operator >> (istream&, str &);
  1489.  
  1490.             Overload istream input operator to support str objects.
  1491.  
  1492.             
  1493.                str a;
  1494.                cin >> a;     // read string from keyboard and store in a
  1495.             
  1496.             
  1497. <<          friend ostream& operator << (ostream&, const str &);
  1498.  
  1499.             Overload ostream input operator to support str objects.
  1500.  
  1501.             
  1502.  
  1503.                str a("hello there");
  1504.                cout << a << endl;   // write string to screen
  1505.             
  1506.             
  1507. lowercase   str lowercase(const char *);
  1508.  
  1509.             Return lower case of character buffer
  1510.  
  1511.             
  1512.              {
  1513.                str a("Abc");
  1514.                cout << lowercase(a);      // outputs "abc"
  1515.              }
  1516.             
  1517.             
  1518. pad         str pad(const char * s, int padsize, 
  1519.                     int t=str::right, char padchar = '
  1520.             ');
  1521.  
  1522.             Pad (padchar) characters to the right and/or left of s, yielding a
  1523.             string of length (padsize).    The padtype can be one of (right,
  1524.             left, or both).  
  1525.  
  1526.             
  1527.             //
  1528.             // This code performs the following.
  1529.             //
  1530.             // a = "hello there                     "
  1531.             // a = "*********************hello there"
  1532.             // a = "          hello there           "
  1533.             //
  1534.                str origstr("hello there");
  1535.                str a = pad(origstr, 32);
  1536.                a = pad(origstr, 32, str::left,'*');
  1537.                a = pad(origstr, 32, str::both);
  1538.             
  1539.             
  1540. strip       str strip(const char * s, int striptype=str::trailing, 
  1541.                       const char * stripchar);
  1542.  
  1543.             Strip leading and/or trailing characters from (s) and return the
  1544.             resulting str.  The strip type (striptype) can be one of (leading,
  1545.             trailing, or both).  (stripchars) is a character string that
  1546.             contains a set of characters to strip.  The default is to strip
  1547.             trailing spaces and tabs.
  1548.  
  1549.             
  1550.             Example strip:
  1551.             
  1552.             //
  1553.             // This code performs the following.
  1554.             //
  1555.             //    a = "********hello there        "
  1556.             //    a = "hello there        "
  1557.             //    a = "hello there"
  1558.             //
  1559.                str origstr("********hello there        ");
  1560.                str a = strip(origstr);
  1561.                a = strip(origstr, str::leading,"*");
  1562.                a = strip(origstr, str::both," *");
  1563.             
  1564.  
  1565. strip       str strip(const char * s, int striptype=trailing, char stripchar);
  1566.  
  1567.             Strip leading and/or trailing characters (as defined by stripchar)
  1568.             from s and return the resulting str.   The strip type (striptype)
  1569.             can be one of (leading, trailing, or both).
  1570.  
  1571.             //
  1572.             // This code performs the following.
  1573.             //
  1574.             //    a = "********hello there"
  1575.             //    a = "hello there        "
  1576.             //
  1577.                str origstr("********hello there        ");
  1578.                str a = strip(origstr, str::trailing,' ');
  1579.                a = strip(origstr, str::leading,'*');
  1580.             
  1581.             
  1582. uppercase   str uppercase(const char *); 
  1583.  
  1584.             Return upper case of character buffer
  1585.  
  1586.             
  1587.              {
  1588.                str a("Abc");
  1589.                cout << uppercase(a);   // outputs "ABC"
  1590.              }
  1591.             
  1592.  
  1593.  
  1594.   PROTECTED
  1595. STATIC MEMBER
  1596.   FUNCTIONS
  1597.  
  1598. setDefaultCaseSensitive   
  1599.             void setDefaultCaseSensitive(int val);
  1600.  
  1601.             Set the default case sensitivity to val.  The default is used when
  1602.             creating new instances of str.
  1603.  
  1604.  
  1605. regX CLASS REFERENCE
  1606. constructor   regX(void); 
  1607.  
  1608.             Default constructor a regular expression.   User should assign
  1609.             regular expression using operator =  before using it.
  1610.  
  1611.  
  1612. constructor   regX(const char * regexp); 
  1613.  
  1614.             Create a regular expression defined by the pattern (regexp).   
  1615.             The regular expression is automatically compiled.
  1616.  
  1617.             
  1618.  
  1619. constructor   regX(const regX& regexp); 
  1620.  
  1621.             Copy constructor for regular expressions.
  1622.  
  1623.             
  1624.  
  1625. =           regX& operator=(const char * regexp);
  1626.  
  1627.             Use the regular expression defined by regexp.   The regular
  1628.             expression is automatically compiled.
  1629.  
  1630.             
  1631.  
  1632. =           regX& operator=(const regX& regexp);
  1633.  
  1634.             Use the regular expression defined by regexp.   
  1635.  
  1636.             
  1637.  
  1638. error       int error(void) const;
  1639.  
  1640.             Return 1 if there was an error in compiling the regular
  1641.             expression.
  1642.  
  1643.  
  1644.  
  1645. index       int index(const char * searchStr, int * matchLenPtr,  
  1646.                       int start=0, int caseSensitive=1);
  1647.  
  1648.             Search for this regular expression in the character buffer
  1649.             searchStr starting at position start.  If the match is found save
  1650.             the length of the match in *matchLenPtr.  Case sensitivity is
  1651.             determined by caseSensitive).   Return position where match is
  1652.             found or -1 if no match is found.
  1653.  
  1654.  
  1655.  
  1656.  
  1657.